package br.ufrj.dcc.ad.simulacao;

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import br.ufrj.dcc.ad.cliente.Cliente;
import br.ufrj.dcc.ad.criterioParada.CriterioDeParadaPorNumeroDeServicos;
import br.ufrj.dcc.ad.estatistica.GeradorEstatistica;
import br.ufrj.dcc.ad.simulador.Simulador;

public class Simulacao {

	private Simulador simulador;
	private GeradorEstatistica estatistica;

	public Simulacao(Simulador simulador, GeradorEstatistica estatistica) {
		this.simulador = simulador;
		this.estatistica = estatistica;
	}

	public void rodaSimulacao(int numeroDeRodadas){

		List<Double> mediasAmostraisTempoEspera = new ArrayList<Double>();
		List<Double> gastosEnergiaPorUnidadeTempoServidor = new ArrayList<Double>();

		for(int i = 0; i < numeroDeRodadas; i++){
			this.simulador.simula();

			List<Double> amostrasTempoEspera = new ArrayList<Double>();
			for (Cliente cliente : this.simulador.getClientesAtendidos()) {
				amostrasTempoEspera.add(cliente.getTempoEspera());
			}
			double mediaAmostralTempoEspera = this.estatistica.media(amostrasTempoEspera);
			//System.out.println("Media Amostral Tempo de Espera: " + mediaAmostralTempoEspera);
			mediasAmostraisTempoEspera.add(mediaAmostralTempoEspera);


			//System.out.println("Servidor: " + ((SimuladorMG1)this.simulador).getServidor().getConsumoEnergiaPorUnidadeTempo());
			gastosEnergiaPorUnidadeTempoServidor.add(this.simulador.getServidor().getConsumoEnergiaTotal() / this.simulador.getTempoDecorridoDesdeInicioSimulacao());

			this.simulador.setCriterioDeParada(new CriterioDeParadaPorNumeroDeServicos(numeroDeRodadas));
			
			for(Cliente c : this.simulador.getClientesAtendidos()){
				System.out.println(c);
			}
			this.simulador.setClientesAtendidos(new ArrayList<Cliente>());
		}

		double mediaTempoEspera = this.estatistica.media(mediasAmostraisTempoEspera);
		System.out.println("Media do Tempo de Espera de um Cliente: " + mediaTempoEspera); 
		System.out.println("Intervalo de Confianca: ["
				+
				this.estatistica.intervaloDeConfiancaParaMenos(mediaTempoEspera, this.estatistica.desvioPadrao(mediasAmostraisTempoEspera, mediaTempoEspera), mediasAmostraisTempoEspera.size())
				+
				", "
				+
				this.estatistica.intervaloDeConfiancaParaMais(mediaTempoEspera, this.estatistica.desvioPadrao(mediasAmostraisTempoEspera, mediaTempoEspera), mediasAmostraisTempoEspera.size())
				+
				"]");

		double mediaGastoServidor = this.estatistica.media(gastosEnergiaPorUnidadeTempoServidor);
		System.out.println("Media do Gasto de  Energia Por Unidade de Tempo Do Servidor: " + mediaGastoServidor);
		System.out.println("Intervalo de Confianca: ["
				+
				this.estatistica.intervaloDeConfiancaParaMenos(mediaGastoServidor, this.estatistica.desvioPadrao(gastosEnergiaPorUnidadeTempoServidor, mediaGastoServidor), gastosEnergiaPorUnidadeTempoServidor.size())
				+
				", "
				+
				this.estatistica.intervaloDeConfiancaParaMais(mediaGastoServidor, this.estatistica.desvioPadrao(mediasAmostraisTempoEspera, mediaGastoServidor), gastosEnergiaPorUnidadeTempoServidor.size())
				+
				"]");

//		this.exportToCsv(mediasAmostraisTempoEspera, "1000");
	}

	public Simulador getSimulador() {
		return simulador;
	}

	public void setSimulador(Simulador simulador) {
		this.simulador = simulador;
	}

	public GeradorEstatistica getEstatistica() {
		return estatistica;
	}

	public void setEstatistica(GeradorEstatistica estatistica) {
		this.estatistica = estatistica;
	}

	public void exportToCsv(List<? extends Number> valores, String nomeArquivo){

		try{
			FileWriter fw = new FileWriter(nomeArquivo + ".csv");
			for (int index = 0; index < valores.size(); index++)
			{
				if (index == valores.size() - 1)
				{
					fw.append(valores.get(index).toString());
				}
				else
				{
					fw.append(valores.get(index).toString());
					fw.append(",");
				}

			}

			fw.flush();
			fw.close();
		}catch(IOException e){
			throw new RuntimeException(e);
		}
	}

}
